#pragma once

#include <AVUIAnimatable.h>
#include <AVUIRect3D.h>

namespace AVUI {

class Transform3D;

/// <summary>Provides generalized transformation support for 3-D objects. </summary>
class GeneralTransform3D : public Animatable
{
public:
    DECLARE_ELEMENT(GeneralTransform3D, Animatable);

#pragma region Public Methods

    /// <summary>Creates a modifiable clone of this <see cref="T:System.Windows.Media.Media3D.GeneralTransform3D" />, making deep copies of this object's values. </summary>
    /// <returns>A modifiable clone of the current object. The cloned object's <see cref="P:System.Windows.Freezable.IsFrozen" /> property is false even if the source's <see cref="P:System.Windows.Freezable.IsFrozen" /> property is true.</returns>
    TRefCountedPtr<GeneralTransform3D> Clone() { return (GeneralTransform3D*) Animatable::Clone().get_Ptr(); }

    /// <summary>Creates a modifiable clone of this <see cref="T:System.Windows.Media.Media3D.GeneralTransform3D" /> object, making deep copies of this object's current values. Resource references, data bindings, and animations are not copied, but their current values are. </summary>
    /// <returns>A modifiable clone of the current object. The cloned object's <see cref="P:System.Windows.Freezable.IsFrozen" /> property is false even if the source's <see cref="P:System.Windows.Freezable.IsFrozen" /> property is true.</returns>
    TRefCountedPtr<GeneralTransform3D> CloneCurrentValue() { return (GeneralTransform3D*) Animatable::CloneCurrentValue().get_Ptr(); }

    /// <summary>Transforms the specified 3-D point and returns the result.</summary>
    /// <returns>The result of transforming <paramref name="point" />.</returns>
    /// <param name="point">The 3-D point to transform.</param>
    /// <exception cref="T:System.InvalidOperationException">The transform did not succeed.</exception>
    Point3D Transform(const Point3D& point)
    {
        Point3D pointd;
        if (!TryTransform(point, &pointd))
        {
            LibraryThrowException(object_allocate<InvalidOperationException>("Transform failed."));
        }
        return pointd;
    }

    /// <summary>When overridden in a derived class, transforms the specified 3-D bounding box and returns an axis-aligned 3-D bounding box that is exactly large enough to contain it.</summary>
    /// <returns>The smallest axis-aligned 3-D bounding box possible that contains the transformed <paramref name="rect" />.</returns>
    /// <param name="rect">The 3-D bounding box to transform.</param>
    virtual Rect3D TransformBounds(const Rect3D& rect) = 0;
 
    /// <summary>When overridden in a derived class, attempts to transform the specified 3-D point and returns a value that indicates whether the transformation was successful.</summary>
    /// <returns>true if <paramref name="inPoint" /> was transformed; otherwise, false.</returns>
    /// <param name="inPoint">The 3-D point to transform.</param>
    /// <param name="result">The result of transforming <paramref name="inPoint" />.</param>
    virtual bool TryTransform(const Point3D& inPoint, Point3D* pResult) = 0;
 
#pragma endregion Public Methods

#pragma region Public Properties

    /// <summary>Gets the inverse transformation of this <see cref="T:System.Windows.Media.Media3D.GeneralTransform3D" />, if possible.</summary>
    /// <returns>An inverse of this instance, if possible; otherwise, null.</returns>
    virtual TRefCountedPtr<GeneralTransform3D> get_Inverse() = 0;

#pragma endregion Public Properties

#pragma region Internal Properties

    virtual TRefCountedPtr<Transform3D> get_AffineTransform() = 0;

#pragma endregion Internal Properties

};


}; // namespace AVUI

